package com.schoolcloud.gateway.config;

import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.alibaba.fastjson2.JSON;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.schoolcloud.common.model.R;
import com.schoolcloud.common.model.REnum;
import jakarta.annotation.PostConstruct;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * [Sa-Token 权限认证] 配置类
 *
 * @author click33
 */
@Configuration
public class SaTokenConfigure {
    // 注册 Sa-Token全局过滤器
    @Bean
    public SaReactorFilter getSaReactorFilter() {
        return new SaReactorFilter()
                // 拦截地址
                .addInclude("/**")    /* 拦截全部path */
                // 开放地址
                .addExclude(
                        "/auth/**"
                )
                // 鉴权方法：每次访问进入
                .setAuth(obj -> {
                    SaRequest request = SaHolder.getRequest();
                    // 示例：获取 Authorization 请求头
                    String userType = request.getHeader("user-type");
                    //   如果是超级管理员，直接放行
                    if ("admin".equals(userType)&&StpUtil.hasRole("admin")) {
                        return;
                    }
                    System.out.println("不是管理员，继续检查");
                    // 权限认证 -- 不同模块, 校验不同权限
                    SaRouter.match("/front/**","/front/user/enroll", r -> FroUserStpUtil.checkLogin());//前台用户的鉴权
//                    对于social下的接口，只需要对新增，删除，修改进行登录验证
                    SaRouter.match("/social/**").matchMethod("POST", "PUT", "DELETE").check(r -> FroUserStpUtil.checkLogin());
                    SaRouter.match("/system/**", r -> StpUtil.checkPermission("system"));//后台用户的鉴权
                    // 更多匹配 ...  */
                })
                // 异常处理方法：每次setAuth函数出现异常时进入,默认是返回一个错误信息，而不抛异常
                .setError(e -> {
                    if (e instanceof NotLoginException){
//                        告诉前端需要重新登录
                        return  new SaResult(401,e.getMessage(),null);
                    }
                    System.err.println("sa-token异常，应该是权限问题：" + e);
//                无权访问的返回，告诉前端无需重新登,只是该接口无权访问
                    return  new SaResult(403,e.getMessage(),null);
                })
//                返回自定义的结果类
//                    .setError(e -> {
//                    if (e instanceof NotLoginException) {
////                    要求重新登录的返回
//                        System.err.println("错误：" + e);
//                        return JSON.toJSON(R.err(REnum.TOKEN_EXPIRED.getCode(), e.getMessage()));
//                    }
//                    System.err.println("全局异常捕获：" + e);
////                无权访问的返回
//                    return JSON.toJSON(R.err(REnum.FORBIDDEN.getCode(), e.getMessage()));
//                })
                ;
    }




    @PostConstruct
    public void setSaTokenConfig() {
        // 设定 StpUtil 使用的 SaTokenConfig 配置参数对象
        SaTokenConfig sysConfig = new SaTokenConfig();
        sysConfig.setTokenName("token");
        sysConfig.setTimeout(-1);
        sysConfig.setTokenStyle("uuid");
        sysConfig.setIsConcurrent(false);//是否允许多人登录同一个账号
        // 更多设置 ...
        StpUtil.stpLogic.setConfig(sysConfig);

        // 设定 StpUserUtil 使用的 SaTokenConfig 配置参数对象
        SaTokenConfig froConfig = new SaTokenConfig();
        froConfig.setTokenName("token");
        froConfig.setTimeout(-1);
        froConfig.setIsConcurrent(false);
        froConfig.setTokenStyle("uuid");
        // 更多设置 ...
        FroUserStpUtil.stpLogic.setConfig(froConfig);
    }
}
